home *** CD-ROM | disk | FTP | other *** search
- /* xlcont - xlisp control built-in functions */
-
- #include "xlisp.h"
-
- /* external variables */
- extern NODE *xlstack,*xlenv,*xlnewenv,*xlvalue;
- extern NODE *s_unbound;
- extern NODE *s_evalhook,*s_applyhook;
- extern NODE *true;
-
- /* external routines */
- extern NODE *xlxeval();
-
- /* forward declarations */
- FORWARD NODE *let();
- FORWARD NODE *prog();
- FORWARD NODE *progx();
- FORWARD NODE *doloop();
-
- /* xcond - built-in function 'cond' */
- NODE *xcond(args)
- NODE *args;
- {
- NODE *oldstk,arg,list,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&list,NULL);
-
- /* initialize */
- arg.n_ptr = args;
-
- /* initialize the return value */
- val = NULL;
-
- /* find a predicate that is true */
- while (arg.n_ptr) {
-
- /* get the next conditional */
- list.n_ptr = xlmatch(LIST,&arg.n_ptr);
-
- /* evaluate the predicate part */
- if (xlevarg(&list.n_ptr)) {
-
- /* evaluate each expression */
- while (list.n_ptr)
- val = xlevarg(&list.n_ptr);
-
- /* exit the loop */
- break;
- }
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the value */
- return (val);
- }
-
- /* xand - built-in function 'and' */
- NODE *xand(args)
- NODE *args;
- {
- NODE *oldstk,arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,NULL);
-
- /* initialize */
- arg.n_ptr = args;
- val = true;
-
- /* evaluate each argument */
- while (arg.n_ptr)
-
- /* get the next argument */
- if ((val = xlevarg(&arg.n_ptr)) == NULL)
- break;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result value */
- return (val);
- }
-
- /* xor - built-in function 'or' */
- NODE *xor(args)
- NODE *args;
- {
- NODE *oldstk,arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,NULL);
-
- /* initialize */
- arg.n_ptr = args;
- val = NULL;
-
- /* evaluate each argument */
- while (arg.n_ptr)
- if ((val = xlevarg(&arg.n_ptr)))
- break;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result value */
- return (val);
- }
-
- /* xif - built-in function 'if' */
- NODE *xif(args)
- NODE *args;
- {
- NODE *oldstk,testexpr,thenexpr,elseexpr,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&testexpr,&thenexpr,&elseexpr,NULL);
-
- /* get the test expression, then clause and else clause */
- testexpr.n_ptr = xlarg(&args);
- thenexpr.n_ptr = xlarg(&args);
- elseexpr.n_ptr = (args ? xlarg(&args) : NULL);
- xllastarg(args);
-
- /* evaluate the appropriate clause */
- val = xleval(xleval(testexpr.n_ptr) ? thenexpr.n_ptr : elseexpr.n_ptr);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the last value */
- return (val);
- }
-
- /* xlet - built-in function 'let' */
- NODE *xlet(args)
- NODE *args;
- {
- return (let(args,TRUE));
- }
-
- /* xletstar - built-in function 'let*' */
- NODE *xletstar(args)
- NODE *args;
- {
- return (let(args,FALSE));
- }
-
- /* let - common let routine */
- LOCAL NODE *let(args,pflag)
- NODE *args; int pflag;
- {
- NODE *oldstk,*oldenv,*oldnewenv,arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,NULL);
-
- /* initialize */
- arg.n_ptr = args;
-
- /* get the list of bindings and bind the symbols */
- oldnewenv = xlnewenv; oldenv = xlnewenv = xlenv;
- dobindings(xlmatch(LIST,&arg.n_ptr),pflag);
-
- /* execute the code */
- for (val = NULL; arg.n_ptr; )
- val = xlevarg(&arg.n_ptr);
-
- /* unbind the arguments */
- xlunbind(oldenv); xlnewenv = oldnewenv;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* xprog - built-in function 'prog' */
- NODE *xprog(args)
- NODE *args;
- {
- return (prog(args,TRUE));
- }
-
- /* xprogstar - built-in function 'prog*' */
- NODE *xprogstar(args)
- NODE *args;
- {
- return (prog(args,FALSE));
- }
-
- /* prog - common prog routine */
- LOCAL NODE *prog(args,pflag)
- NODE *args; int pflag;
- {
- NODE *oldstk,*oldenv,*oldnewenv,arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,NULL);
-
- /* initialize */
- arg.n_ptr = args;
-
- /* get the list of bindings and bind the symbols */
- oldnewenv = xlnewenv; oldenv = xlnewenv = xlenv;
- dobindings(xlmatch(LIST,&arg.n_ptr),pflag);
-
- /* execute the code */
- tagblock(arg.n_ptr,&val);
-
- /* unbind the arguments */
- xlunbind(oldenv); xlnewenv = oldnewenv;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* xgo - built-in function 'go' */
- NODE *xgo(args)
- NODE *args;
- {
- NODE *label;
-
- /* get the target label */
- label = xlarg(&args);
- xllastarg(args);
-
- /* transfer to the label */
- xlgo(label);
- }
-
- /* xreturn - built-in function 'return' */
- NODE *xreturn(args)
- NODE *args;
- {
- NODE *val;
-
- /* get the return value */
- val = (args ? xlarg(&args) : NULL);
- xllastarg(args);
-
- /* return from the inner most block */
- xlreturn(val);
- }
-
- /* xprog1 - built-in function 'prog1' */
- NODE *xprog1(args)
- NODE *args;
- {
- return (progx(args,1));
- }
-
- /* xprog2 - built-in function 'prog2' */
- NODE *xprog2(args)
- NODE *args;
- {
- return (progx(args,2));
- }
-
- /* progx - common progx code */
- LOCAL NODE *progx(args,n)
- NODE *args; int n;
- {
- NODE *oldstk,arg,val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&val,NULL);
-
- /* initialize */
- arg.n_ptr = args;
-
- /* evaluate the first n expressions */
- while (n--)
- val.n_ptr = xlevarg(&arg.n_ptr);
-
- /* evaluate each remaining argument */
- while (arg.n_ptr)
- xlevarg(&arg.n_ptr);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the last test expression value */
- return (val.n_ptr);
- }
-
- /* xprogn - built-in function 'progn' */
- NODE *xprogn(args)
- NODE *args;
- {
- NODE *oldstk,arg,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,NULL);
-
- /* initialize */
- arg.n_ptr = args;
-
- /* evaluate each remaining argument */
- for (val = NULL; arg.n_ptr; )
- val = xlevarg(&arg.n_ptr);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the last test expression value */
- return (val);
- }
-
- /* xdo - built-in function 'do' */
- NODE *xdo(args)
- NODE *args;
- {
- return (doloop(args,TRUE));
- }
-
- /* xdostar - built-in function 'do*' */
- NODE *xdostar(args)
- NODE *args;
- {
- return (doloop(args,FALSE));
- }
-
- /* doloop - common do routine */
- LOCAL NODE *doloop(args,pflag)
- NODE *args; int pflag;
- {
- NODE *oldstk,*oldenv,*oldnewenv,arg,blist,clist,test,*rval;
- int rbreak;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&blist,&clist,&test,NULL);
-
- /* initialize */
- arg.n_ptr = args;
-
- /* get the list of bindings and bind the symbols */
- blist.n_ptr = xlmatch(LIST,&arg.n_ptr);
- oldnewenv = xlnewenv; oldenv = xlnewenv = xlenv;
- dobindings(blist.n_ptr,pflag);
-
- /* get the exit test and result forms */
- clist.n_ptr = xlmatch(LIST,&arg.n_ptr);
- test.n_ptr = xlarg(&clist.n_ptr);
-
- /* execute the loop as long as the test is false */
- rbreak = FALSE;
- while (xleval(test.n_ptr) == NULL) {
-
- /* execute the body of the loop */
- if (tagblock(arg.n_ptr,&rval)) {
- rbreak = TRUE;
- break;
- }
-
- /* update the looping variables */
- doupdates(blist.n_ptr,pflag);
- }
-
- /* evaluate the result expression */
- if (!rbreak)
- for (rval = NULL; consp(clist.n_ptr); )
- rval = xlevarg(&clist.n_ptr);
-
- /* unbind the arguments */
- xlunbind(oldenv); xlnewenv = oldnewenv;
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (rval);
- }
-
- /* xdolist - built-in function 'dolist' */
- NODE *xdolist(args)
- NODE *args;
- {
- NODE *oldstk,*oldenv,arg,clist,sym,list,val,*rval;
- int rbreak;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&clist,&sym,&list,&val,NULL);
-
- /* initialize */
- arg.n_ptr = args;
-
- /* get the control list (sym list result-expr) */
- clist.n_ptr = xlmatch(LIST,&arg.n_ptr);
- sym.n_ptr = xlmatch(SYM,&clist.n_ptr);
- list.n_ptr = xlevmatch(LIST,&clist.n_ptr);
- val.n_ptr = (clist.n_ptr ? xlarg(&clist.n_ptr) : NULL);
-
- /* initialize the local environment */
- oldenv = xlenv;
- xlsbind(sym.n_ptr,NULL);
-
- /* loop through the list */
- rbreak = FALSE;
- for (; consp(list.n_ptr); list.n_ptr = cdr(list.n_ptr)) {
-
- /* bind the symbol to the next list element */
- sym.n_ptr->n_symvalue = car(list.n_ptr);
-
- /* execute the loop body */
- if (tagblock(arg.n_ptr,&rval)) {
- rbreak = TRUE;
- break;
- }
- }
-
- /* evaluate the result expression */
- if (!rbreak) {
- sym.n_ptr->n_symvalue = NULL;
- rval = xleval(val.n_ptr);
- }
-
- /* unbind the arguments */
- xlunbind(oldenv);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (rval);
- }
-
- /* xdotimes - built-in function 'dotimes' */
- NODE *xdotimes(args)
- NODE *args;
- {
- NODE *oldstk,*oldenv,arg,clist,sym,val,*rval;
- int rbreak,cnt,i;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,&clist,&sym,&val,NULL);
-
- /* initialize */
- arg.n_ptr = args;
-
- /* get the control list (sym list result-expr) */
- clist.n_ptr = xlmatch(LIST,&arg.n_ptr);
- sym.n_ptr = xlmatch(SYM,&clist.n_ptr);
- cnt = xlevmatch(INT,&clist.n_ptr)->n_int;
- val.n_ptr = (clist.n_ptr ? xlarg(&clist.n_ptr) : NULL);
-
- /* initialize the local environment */
- oldenv = xlenv;
- xlsbind(sym.n_ptr,NULL);
-
- /* loop through for each value from zero to cnt-1 */
- rbreak = FALSE;
- for (i = 0; i < cnt; i++) {
-
- /* bind the symbol to the next list element */
- sym.n_ptr->n_symvalue = newnode(INT);
- sym.n_ptr->n_symvalue->n_int = i;
-
- /* execute the loop body */
- if (tagblock(arg.n_ptr,&rval)) {
- rbreak = TRUE;
- break;
- }
- }
-
- /* evaluate the result expression */
- if (!rbreak) {
- sym.n_ptr->n_symvalue = newnode(INT);
- sym.n_ptr->n_symvalue->n_int = cnt;
- rval = xleval(val.n_ptr);
- }
-
- /* unbind the arguments */
- xlunbind(oldenv);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (rval);
- }
-
- /* xcatch - built-in function 'catch' */
- NODE *xcatch(args)
- NODE *args;
- {
- NODE *oldstk,tag,arg,*val;
- CONTEXT cntxt;
-
- /* create a new stack frame */
- oldstk = xlsave(&tag,&arg,NULL);
-
- /* initialize */
- tag.n_ptr = xlevarg(&args);
- arg.n_ptr = args;
- val = NULL;
-
- /* establish an execution context */
- xlbegin(&cntxt,CF_THROW,tag.n_ptr);
-
- /* check for 'throw' */
- if (setjmp(cntxt.c_jmpbuf))
- val = xlvalue;
-
- /* otherwise, evaluate the remainder of the arguments */
- else {
- while (arg.n_ptr)
- val = xlevarg(&arg.n_ptr);
- }
- xlend(&cntxt);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* xthrow - built-in function 'throw' */
- NODE *xthrow(args)
- NODE *args;
- {
- NODE *tag,*val;
-
- /* get the tag and value */
- tag = xlarg(&args);
- val = (args ? xlarg(&args) : NULL);
- xllastarg(args);
-
- /* throw the tag */
- xlthrow(tag,val);
- }
-
- /* xerror - built-in function 'error' */
- NODE *xerror(args)
- NODE *args;
- {
- char *emsg; NODE *arg;
-
- /* get the error message and the argument */
- emsg = xlmatch(STR,&args)->n_str;
- arg = (args ? xlarg(&args) : s_unbound);
- xllastarg(args);
-
- /* signal the error */
- xlerror(emsg,arg);
- }
-
- /* xcerror - built-in function 'cerror' */
- NODE *xcerror(args)
- NODE *args;
- {
- char *cmsg,*emsg; NODE *arg;
-
- /* get the correction message, the error message, and the argument */
- cmsg = xlmatch(STR,&args)->n_str;
- emsg = xlmatch(STR,&args)->n_str;
- arg = (args ? xlarg(&args) : s_unbound);
- xllastarg(args);
-
- /* signal the error */
- xlcerror(cmsg,emsg,arg);
-
- /* return nil */
- return (NULL);
- }
-
- /* xbreak - built-in function 'break' */
- NODE *xbreak(args)
- NODE *args;
- {
- char *emsg; NODE *arg;
-
- /* get the error message */
- emsg = (args ? xlmatch(STR,&args)->n_str : "**BREAK**");
- arg = (args ? xlarg(&args) : s_unbound);
- xllastarg(args);
-
- /* enter the break loop */
- xlbreak(emsg,arg);
-
- /* return nil */
- return (NULL);
- }
-
- /* xerrset - built-in function 'errset' */
- NODE *xerrset(args)
- NODE *args;
- {
- NODE *oldstk,expr,flag,*val;
- CONTEXT cntxt;
-
- /* create a new stack frame */
- oldstk = xlsave(&expr,&flag,NULL);
-
- /* get the expression and the print flag */
- expr.n_ptr = xlarg(&args);
- flag.n_ptr = (args ? xlarg(&args) : true);
- xllastarg(args);
-
- /* establish an execution context */
- xlbegin(&cntxt,CF_ERROR,flag.n_ptr);
-
- /* check for error */
- if (setjmp(cntxt.c_jmpbuf))
- val = NULL;
-
- /* otherwise, evaluate the expression */
- else {
- expr.n_ptr = xleval(expr.n_ptr);
- val = newnode(LIST);
- rplaca(val,expr.n_ptr);
- }
- xlend(&cntxt);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* xevalhook - eval hook function */
- NODE *xevalhook(args)
- NODE *args;
- {
- NODE *oldstk,*oldenv,expr,ehook,ahook,*val;
-
- /* create a new stack frame */
- oldstk = xlsave(&expr,&ehook,&ahook,NULL);
-
- /* get the expression and the hook functions */
- expr.n_ptr = xlarg(&args);
- ehook.n_ptr = xlarg(&args);
- ahook.n_ptr = xlarg(&args);
- xllastarg(args);
-
- /* bind *evalhook* and *applyhook* to the hook functions */
- oldenv = xlenv;
- xlsbind(s_evalhook,ehook.n_ptr);
- xlsbind(s_applyhook,ahook.n_ptr);
-
- /* evaluate the expression (bypassing *evalhook*) */
- val = xlxeval(expr.n_ptr);
-
- /* unbind the hook variables */
- xlunbind(oldenv);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* return the result */
- return (val);
- }
-
- /* dobindings - handle bindings for let/let*, prog/prog*, do/do* */
- LOCAL dobindings(blist,pflag)
- NODE *blist; int pflag;
- {
- NODE *oldstk,list,bnd,sym,val;
-
- /* create a new stack frame */
- oldstk = xlsave(&list,&bnd,&sym,&val,NULL);
-
- /* bind each symbol in the list of bindings */
- for (list.n_ptr = blist; consp(list.n_ptr); list.n_ptr = cdr(list.n_ptr)) {
-
- /* get the next binding */
- bnd.n_ptr = car(list.n_ptr);
-
- /* handle a symbol */
- if (symbolp(bnd.n_ptr)) {
- sym.n_ptr = bnd.n_ptr;
- val.n_ptr = NULL;
- }
-
- /* handle a list of the form (symbol expr) */
- else if (consp(bnd.n_ptr)) {
- sym.n_ptr = xlmatch(SYM,&bnd.n_ptr);
- val.n_ptr = xlevarg(&bnd.n_ptr);
- }
- else
- xlfail("bad binding");
-
- /* bind the value to the symbol */
- if (pflag)
- xlbind(sym.n_ptr,val.n_ptr);
- else
- xlsbind(sym.n_ptr,val.n_ptr);
- }
-
- /* fix the bindings on a parallel let */
- if (pflag)
- xlfixbindings();
-
- /* restore the previous stack frame */
- xlstack = oldstk;
- }
-
- /* doupdates - handle updates for do/do* */
- doupdates(blist,pflag)
- NODE *blist; int pflag;
- {
- NODE *oldstk,*oldenv,list,bnd,sym,val;
-
- /* create a new stack frame */
- oldstk = xlsave(&list,&bnd,&sym,&val,NULL);
-
- /* initialize the local environment */
- if (pflag)
- oldenv = xlenv;
-
- /* bind each symbol in the list of bindings */
- for (list.n_ptr = blist; consp(list.n_ptr); list.n_ptr = cdr(list.n_ptr)) {
-
- /* get the next binding */
- bnd.n_ptr = car(list.n_ptr);
-
- /* handle a list of the form (symbol expr) */
- if (consp(bnd.n_ptr)) {
- sym.n_ptr = xlmatch(SYM,&bnd.n_ptr);
- bnd.n_ptr = cdr(bnd.n_ptr);
- if (bnd.n_ptr) {
- val.n_ptr = xlevarg(&bnd.n_ptr);
- if (pflag)
- xlbind(sym.n_ptr,val.n_ptr);
- else
- sym.n_ptr->n_symvalue = val.n_ptr;
- }
- }
- }
-
- /* fix the bindings on a parallel let */
- if (pflag) {
- xlfixbindings();
- xlenv = oldenv;
- }
-
- /* restore the previous stack frame */
- xlstack = oldstk;
- }
-
- /* tagblock - execute code within a block and tagbody */
- int tagblock(code,pval)
- NODE *code,**pval;
- {
- NODE *oldstk,arg;
- CONTEXT cntxt;
- int type;
-
- /* create a new stack frame */
- oldstk = xlsave(&arg,NULL);
-
- /* initialize */
- arg.n_ptr = code;
-
- /* establish an execution context */
- xlbegin(&cntxt,CF_GO|CF_RETURN,arg.n_ptr);
-
- /* check for a 'return' */
- if ((type = setjmp(cntxt.c_jmpbuf)) == CF_RETURN) {
- xlstack = oldstk;
- *pval = xlvalue;
- return (TRUE);
- }
-
- /* otherwise, enter the body */
- else {
-
- /* check for a 'go' */
- if (type == CF_GO)
- arg.n_ptr = xlvalue;
-
- /* evaluate each expression in the body */
- while (consp(arg.n_ptr))
- if (consp(car(arg.n_ptr)))
- xlevarg(&arg.n_ptr);
- else
- arg.n_ptr = cdr(arg.n_ptr);
- }
- xlend(&cntxt);
-
- /* restore the previous stack frame */
- xlstack = oldstk;
-
- /* set the value to nil and say we fell out the bottom of the block */
- *pval = NULL;
- return (FALSE);
- }